package lsp

import (
	"encoding/json"
	"fmt"
	"go/token"
	"io"
	"log"
	"os"
	"strings"
	"sync"

	"github.com/yourusername/gox/pkg/generator"
	goxparser "github.com/yourusername/gox/pkg/parser"
)

// Server GoX 语言服务器
type Server struct {
	reader io.Reader
	writer io.Writer

	// 文档缓存
	documents sync.Map // map[string]*Document

	// 解析器
	goxParser *goxparser.Parser
	generator *generator.Generator
	fset      *token.FileSet
}

// Document 文档信息
type Document struct {
	URI     string
	Version int
	Content string
	AST     *goxparser.GoxFile
}

// NewServer 创建新的语言服务器
func NewServer(reader io.Reader, writer io.Writer) *Server {
	fset := token.NewFileSet()
	return &Server{
		reader:    reader,
		writer:    writer,
		goxParser: goxparser.NewParser(),
		generator: generator.NewGenerator(fset),
		fset:      fset,
	}
}

// Start 启动语言服务器
func (s *Server) Start() error {
	decoder := json.NewDecoder(s.reader)

	for {
		var req Request
		if err := decoder.Decode(&req); err != nil {
			if err == io.EOF {
				return nil
			}
			return fmt.Errorf("解码请求失败: %w", err)
		}

		go s.handleRequest(req)
	}
}

// Request LSP 请求
type Request struct {
	ID     interface{} `json:"id"`
	Method string      `json:"method"`
	Params interface{} `json:"params"`
}

// Response LSP 响应
type Response struct {
	ID     interface{} `json:"id,omitempty"`
	Result interface{} `json:"result,omitempty"`
	Error  *Error      `json:"error,omitempty"`
}

// Error LSP 错误
type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// Notification LSP 通知
type Notification struct {
	Method string      `json:"method"`
	Params interface{} `json:"params"`
}

// handleRequest 处理请求
func (s *Server) handleRequest(req Request) {
	switch req.Method {
	case "initialize":
		s.handleInitialize(req)
	case "textDocument/didOpen":
		s.handleDidOpen(req)
	case "textDocument/didChange":
		s.handleDidChange(req)
	case "textDocument/didSave":
		s.handleDidSave(req)
	case "textDocument/completion":
		s.handleCompletion(req)
	case "textDocument/hover":
		s.handleHover(req)
	case "textDocument/definition":
		s.handleDefinition(req)
	case "textDocument/documentSymbol":
		s.handleDocumentSymbol(req)
	case "textDocument/publishDiagnostics":
		s.handleDiagnostics(req)
	default:
		log.Printf("未知方法: %s", req.Method)
	}
}

// InitializeParams 初始化参数
type InitializeParams struct {
	ProcessID    int    `json:"processId"`
	RootPath     string `json:"rootPath"`
	RootURI      string `json:"rootUri"`
	Capabilities struct {
		TextDocument struct {
			Completion struct {
				CompletionItem struct {
					SnippetSupport bool `json:"snippetSupport"`
				} `json:"completionItem"`
			} `json:"completion"`
		} `json:"textDocument"`
	} `json:"capabilities"`
}

// handleInitialize 处理初始化
func (s *Server) handleInitialize(req Request) {
	capabilities := map[string]interface{}{
		"textDocumentSync": 1, // 完全同步
		"completionProvider": map[string]interface{}{
			"triggerCharacters": []string{"{", "#", "<"},
		},
		"hoverProvider":          true,
		"definitionProvider":     true,
		"documentSymbolProvider": true,
		"diagnosticProvider":     true,
	}

	result := map[string]interface{}{
		"capabilities": capabilities,
	}

	s.sendResponse(Response{
		ID:     req.ID,
		Result: result,
	})
}

// DidOpenTextDocumentParams 文档打开参数
type DidOpenTextDocumentParams struct {
	TextDocument struct {
		URI        string `json:"uri"`
		LanguageID string `json:"languageId"`
		Version    int    `json:"version"`
		Text       string `json:"text"`
	} `json:"textDocument"`
}

// handleDidOpen 处理文档打开
func (s *Server) handleDidOpen(req Request) {
	var params DidOpenTextDocumentParams
	if err := s.unmarshalParams(req.Params, &params); err != nil {
		log.Printf("解析 didOpen 参数失败: %v", err)
		return
	}

	doc := &Document{
		URI:     params.TextDocument.URI,
		Version: params.TextDocument.Version,
		Content: params.TextDocument.Text,
	}

	// 解析文档
	s.parseDocument(doc)

	// 缓存文档
	s.documents.Store(params.TextDocument.URI, doc)

	// 发送诊断信息
	s.publishDiagnostics(doc)
}

// DidChangeTextDocumentParams 文档变更参数
type DidChangeTextDocumentParams struct {
	TextDocument struct {
		URI     string `json:"uri"`
		Version int    `json:"version"`
	} `json:"textDocument"`
	ContentChanges []struct {
		Text string `json:"text"`
	} `json:"contentChanges"`
}

// handleDidChange 处理文档变更
func (s *Server) handleDidChange(req Request) {
	var params DidChangeTextDocumentParams
	if err := s.unmarshalParams(req.Params, &params); err != nil {
		log.Printf("解析 didChange 参数失败: %v", err)
		return
	}

	docInterface, exists := s.documents.Load(params.TextDocument.URI)
	if !exists {
		return
	}

	doc := docInterface.(*Document)
	doc.Version = params.TextDocument.Version

	// 更新文档内容
	if len(params.ContentChanges) > 0 {
		doc.Content = params.ContentChanges[0].Text
	}

	// 重新解析
	s.parseDocument(doc)

	// 发送诊断信息
	s.publishDiagnostics(doc)
}

// handleDidSave 处理文档保存
func (s *Server) handleDidSave(req Request) {
	// 可以在这里触发编译等操作
}

// Position LSP 位置
type Position struct {
	Line      int `json:"line"`
	Character int `json:"character"`
}

// Range LSP 范围
type Range struct {
	Start Position `json:"start"`
	End   Position `json:"end"`
}

// CompletionParams 补全参数
type CompletionParams struct {
	TextDocument struct {
		URI string `json:"uri"`
	} `json:"textDocument"`
	Position Position `json:"position"`
}

// CompletionItem 补全项
type CompletionItem struct {
	Label         string `json:"label"`
	Kind          int    `json:"kind"`
	Detail        string `json:"detail,omitempty"`
	Documentation string `json:"documentation,omitempty"`
	InsertText    string `json:"insertText,omitempty"`
}

// handleCompletion 处理代码补全
func (s *Server) handleCompletion(req Request) {
	var params CompletionParams
	if err := s.unmarshalParams(req.Params, &params); err != nil {
		log.Printf("解析补全参数失败: %v", err)
		return
	}

	docInterface, exists := s.documents.Load(params.TextDocument.URI)
	if !exists {
		s.sendResponse(Response{ID: req.ID, Result: []CompletionItem{}})
		return
	}

	doc := docInterface.(*Document)
	items := s.getCompletionItems(doc, params.Position)

	s.sendResponse(Response{
		ID:     req.ID,
		Result: items,
	})
}

// getCompletionItems 获取补全项
func (s *Server) getCompletionItems(doc *Document, pos Position) []CompletionItem {
	var items []CompletionItem

	// SQL 关键字
	sqlKeywords := []string{
		"SELECT", "FROM", "WHERE", "JOIN", "INNER JOIN", "LEFT JOIN",
		"RIGHT JOIN", "ORDER BY", "GROUP BY", "HAVING", "INSERT",
		"UPDATE", "DELETE", "CREATE TABLE", "ALTER TABLE", "DROP TABLE",
	}

	for _, keyword := range sqlKeywords {
		items = append(items, CompletionItem{
			Label:  keyword,
			Kind:   14, // Keyword
			Detail: "SQL关键字",
		})
	}

	// 表达式模板
	items = append(items, CompletionItem{
		Label:      "#{param}",
		Kind:       15, // Snippet
		Detail:     "参数化表达式",
		InsertText: "#{$1}",
	})

	items = append(items, CompletionItem{
		Label:      "{text}",
		Kind:       15, // Snippet
		Detail:     "文本插入表达式",
		InsertText: "{$1}",
	})

	return items
}

// HoverParams 悬停参数
type HoverParams struct {
	TextDocument struct {
		URI string `json:"uri"`
	} `json:"textDocument"`
	Position Position `json:"position"`
}

// Hover 悬停信息
type Hover struct {
	Contents string `json:"contents"`
	Range    *Range `json:"range,omitempty"`
}

// handleHover 处理悬停
func (s *Server) handleHover(req Request) {
	var params HoverParams
	if err := s.unmarshalParams(req.Params, &params); err != nil {
		log.Printf("解析悬停参数失败: %v", err)
		return
	}

	docInterface, exists := s.documents.Load(params.TextDocument.URI)
	if !exists {
		s.sendResponse(Response{ID: req.ID, Result: nil})
		return
	}

	doc := docInterface.(*Document)
	hover := s.getHoverInfo(doc, params.Position)

	s.sendResponse(Response{
		ID:     req.ID,
		Result: hover,
	})
}

// getHoverInfo 获取悬停信息
func (s *Server) getHoverInfo(doc *Document, pos Position) *Hover {
	// 这里可以实现更复杂的悬停逻辑
	return &Hover{
		Contents: "GoX SQL 块 - 支持嵌入式SQL查询",
	}
}

// handleDefinition 处理定义跳转
func (s *Server) handleDefinition(req Request) {
	// 实现定义跳转逻辑
	s.sendResponse(Response{ID: req.ID, Result: nil})
}

// DocumentSymbol 文档符号
type DocumentSymbol struct {
	Name           string           `json:"name"`
	Detail         string           `json:"detail,omitempty"`
	Kind           int              `json:"kind"`
	Range          Range            `json:"range"`
	SelectionRange Range            `json:"selectionRange"`
	Children       []DocumentSymbol `json:"children,omitempty"`
}

// handleDocumentSymbol 处理文档符号
func (s *Server) handleDocumentSymbol(req Request) {
	var params struct {
		TextDocument struct {
			URI string `json:"uri"`
		} `json:"textDocument"`
	}

	if err := s.unmarshalParams(req.Params, &params); err != nil {
		log.Printf("解析文档符号参数失败: %v", err)
		return
	}

	docInterface, exists := s.documents.Load(params.TextDocument.URI)
	if !exists {
		s.sendResponse(Response{ID: req.ID, Result: []DocumentSymbol{}})
		return
	}

	doc := docInterface.(*Document)
	symbols := s.getDocumentSymbols(doc)

	s.sendResponse(Response{
		ID:     req.ID,
		Result: symbols,
	})
}

// getDocumentSymbols 获取文档符号
func (s *Server) getDocumentSymbols(doc *Document) []DocumentSymbol {
	var symbols []DocumentSymbol

	if doc.AST != nil {
		for range doc.AST.SQLBlocks {
			symbol := DocumentSymbol{
				Name:           "SQL块",
				Detail:         "嵌入式SQL查询",
				Kind:           15, // String
				Range:          Range{Start: Position{0, 0}, End: Position{0, 10}},
				SelectionRange: Range{Start: Position{0, 0}, End: Position{0, 10}},
			}
			symbols = append(symbols, symbol)
		}
	}

	return symbols
}

// Diagnostic 诊断信息
type Diagnostic struct {
	Range    Range  `json:"range"`
	Severity int    `json:"severity"`
	Message  string `json:"message"`
}

// handleDiagnostics 处理诊断
func (s *Server) handleDiagnostics(req Request) {
	// 诊断通常是通过 publishDiagnostics 主动发送的
}

// publishDiagnostics 发布诊断信息
func (s *Server) publishDiagnostics(doc *Document) {
	var diagnostics []Diagnostic

	// 检查语法错误
	if doc.AST == nil {
		diagnostics = append(diagnostics, Diagnostic{
			Range: Range{
				Start: Position{0, 0},
				End:   Position{0, 10},
			},
			Severity: 1, // Error
			Message:  "语法解析失败",
		})
	}

	// 发送诊断通知
	notification := Notification{
		Method: "textDocument/publishDiagnostics",
		Params: map[string]interface{}{
			"uri":         doc.URI,
			"diagnostics": diagnostics,
		},
	}

	s.sendNotification(notification)
}

// parseDocument 解析文档
func (s *Server) parseDocument(doc *Document) {
	// 解析 gox 文件
	goxFile, err := s.goxParser.ParseFile(uriToPath(doc.URI), []byte(doc.Content))
	if err != nil {
		log.Printf("解析 gox 文件失败: %v", err)
		doc.AST = nil
		return
	}

	doc.AST = goxFile
}

// 辅助函数
func (s *Server) sendResponse(resp Response) {
	if err := json.NewEncoder(s.writer).Encode(resp); err != nil {
		log.Printf("发送响应失败: %v", err)
	}
}

func (s *Server) sendNotification(notif Notification) {
	if err := json.NewEncoder(s.writer).Encode(notif); err != nil {
		log.Printf("发送通知失败: %v", err)
	}
}

func (s *Server) unmarshalParams(params interface{}, dest interface{}) error {
	data, err := json.Marshal(params)
	if err != nil {
		return err
	}
	return json.Unmarshal(data, dest)
}

func uriToPath(uri string) string {
	if strings.HasPrefix(uri, "file://") {
		return strings.TrimPrefix(uri, "file://")
	}
	return uri
}

// 启动语言服务器的主函数
func StartServer() {
	server := NewServer(os.Stdin, os.Stdout)
	if err := server.Start(); err != nil {
		log.Fatalf("语言服务器启动失败: %v", err)
	}
}
